#include "sem.h"

// 信号量相关函数
// 对环形队列实现互斥与同步(生产者与消费者)

#define SEM_PATHNMAE "../../sem"
#define SEM_PROJ_ID 100

union semun
{
    int val;               /* Value for SETVAL */
    struct semid_ds *buf;  /* Buffer for IPC_STAT, IPC_SET */
    unsigned short *array; /* Array for GETALL, SETALL */
    struct seminfo *__buf; /* Buffer for IPC_INFO
                              (Linux-specific) */
};

int sem_create(int nsems, unsigned short values[])
{
    int semid, ret;
    key_t key;

    key = ftok(SEM_PATHNMAE, SEM_PROJ_ID);

    semid = semget(key, nsems, IPC_CREAT | 0644);
    if (-1 == semid)
    {
        perror("[ERROR] semget()");
        return -1;
    }

    // 初始化信号量集合
    union semun s;
    s.array = values;
    // 设置信号量集合 编号从0开始
    // 将集合中所有信号量值设置为s.array 的数组中的值
    ret = semctl(semid, 0, SETALL, s);
    if (-1 == ret)
    {
        perror("[ERROR] semctl()");
        return -1;
    }

    return semid;
}

// 获取信号量
// 信号量标识 信号量编号
int sem_p(int semid, int semnum)
{
    struct sembuf sops;

    sops.sem_num = semnum;
    sops.sem_op = -1;
    //  sops.sem_flg = SEM_UNDO;

    return semop(semid, &sops, 1);
}

// 释放信号量
// 信号量标识 信号量编号
int sem_v(int semid, int semnum)
{
    struct sembuf sops;

    sops.sem_num = semnum;
    sops.sem_op = 1;
    // sops.sem_flg = SEM_UNDO;

    return semop(semid, &sops, 1);
}

// 删除信号量
int sem_delete(int semid)
{
    return semctl(semid, 0, IPC_RMID, NULL);
}